// nvue操作dom的库，用于获取dom的尺寸信息
const dom = uni.requireNativePlugin('dom');
const bindingX = uni.requireNativePlugin('bindingx');
const animation = uni.requireNativePlugin('animation');

export default {
  data() {
    return {
      // 所有按钮的总宽度
      buttonsWidth: 0,
      // 是否正在移动中
      moving: false
    };
  },
  computed: {
    // 获取过渡时间
    getDuratin() {
      let duration = String(this.duration);
      // 如果ms为单位，返回ms的数值部分
      if (duration.indexOf('ms') >= 0) return parseInt(duration);
      // 如果s为单位，为了得到ms的数值，需要乘以1000
      if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000;
      // 如果值传了数值，且小于30，认为是s单位
      duration = Number(duration);
      return duration < 30 ? duration * 1000 : duration;
    }
  },
  watch: {
    show(n) {
      if (n) {
        this.moveCellByAnimation('open');
      } else {
        this.moveCellByAnimation('close');
      }
    }
  },
  mounted() {
    this.initialize();
  },
  methods: {
    initialize() {
      this.queryRect();
    },
    // 关闭单元格，用于打开一个，自动关闭其他单元格的场景
    closeHandler() {
      if (this.status === 'open') {
        // 如果在打开状态下，进行点击的话，直接关闭单元格
        return this.moveCellByAnimation('close') && this.unbindBindingX();
      }
    },
    // 点击单元格
    clickHandler() {
      // 如果在移动中被点击，进行忽略
      if (this.moving) return;
      // 尝试关闭其他打开的单元格
      this.parent && this.parent.closeOther(this);
      if (this.status === 'open') {
        // 如果在打开状态下，进行点击的话，直接关闭单元格
        return this.moveCellByAnimation('close') && this.unbindBindingX();
      }
    },
    // 滑动单元格
    onTouchstart(e) {
      // 如果当前正在移动中，或者disabled状态，则返回
      if (this.moving || this.disabled) {
        return this.unbindBindingX();
      }
      if (this.status === 'open') {
        // 如果在打开状态下，进行点击的话，直接关闭单元格
        return this.moveCellByAnimation('close') && this.unbindBindingX();
      }
      // 特殊情况下，e可能不为一个对象
      e?.stopPropagation && e.stopPropagation();
      e?.preventDefault && e.preventDefault();
      this.moving = true;
      // 获取元素ref
      const content = this.getContentRef();
      let expression = `min(max(${-this.buttonsWidth}, x), 0)`;
      // 尝试关闭其他打开的单元格
      this.parent && this.parent.closeOther(this);

      // 阿里为了KPI而开源的BindingX
      this.panEvent = bindingX.bind({
        anchor: content,
        eventType: 'pan',
        props: [{
          element: content,
          // 绑定width属性，设置其宽度值
          property: 'transform.translateX',
          expression
        }]
      }, (res) => {
        this.moving = false;
        if (res.state === 'end' || res.state === 'exit') {
          const deltaX = res.deltaX;
          if (deltaX <= -this.buttonsWidth || deltaX >= 0) {
            // 如果触摸滑动的过程中，大于单元格的总宽度，或者大于0，意味着已经动过滑动达到了打开或者关闭的状态
            // 这里直接进行状态的标记
            this.$nextTick(() => {
              this.status = deltaX <= -this.buttonsWidth ? 'open' : 'close';
            });
          } else if (Math.abs(deltaX) > uni.$u.getPx(this.threshold)) {
            // 在移动大于阈值、并且小于总按钮宽度时，进行自动打开或者关闭
            // 移动距离大于0时，意味着需要关闭状态
            if (Math.abs(deltaX) < this.buttonsWidth) {
              this.moveCellByAnimation(deltaX > 0 ? 'close' : 'open');
            }
          } else {
            // 在小于阈值时，进行关闭操作(如果在打开状态下，将不会执行bindingX)
            this.moveCellByAnimation('close');
          }
        }
      });
    },
    // 释放bindingX
    unbindBindingX() {
      // 释放上一次的资源
      if (this?.panEvent?.token != 0) {
        bindingX.unbind({
          token: this.panEvent?.token,
          // pan为手势事件
          eventType: 'pan'
        });
      }
    },
    // 查询按钮节点信息
    queryRect() {
      // 历遍所有按钮数组，通过getRectByDom返回一个promise
      const promiseAll = this.options.map((item, index) => {
        return this.getRectByDom(this.$refs[`u-swipe-action-item__right__button-${index}`][0]);
      });
      // 通过promise.all方法，让所有按钮的查询结果返回一个数组的形式
      Promise.all(promiseAll).then((sizes) => {
        this.buttons = sizes;
        // 计算所有按钮总宽度
        this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0);
      });
    },
    // 通过nvue的dom模块，查询节点信息
    getRectByDom(ref) {
      return new Promise((resolve) => {
        dom.getComponentRect(ref, (res) => {
          resolve(res.size);
        });
      });
    },
    // 移动单元格到左边或者右边尽头
    moveCellByAnimation(status = 'open') {
      if (this.moving) return;
      // 标识当前状态
      this.moveing = true;
      const content = this.getContentRef();
      const x = status === 'open' ? -this.buttonsWidth : 0;
      animation.transition(content, {
        styles: {
          transform: `translateX(${x}px)`
        },
        duration: uni.$u.getDuration(this.duration, false),
        timingFunction: 'ease-in-out'
      }, () => {
        this.moving = false;
        this.status = status;
        this.unbindBindingX();
      });
    },
    // 获取元素ref
    getContentRef() {
      return this.$refs['u-swipe-action-item__content'].ref;
    },
    beforeDestroy() {
      this.unbindBindingX();
    }
  }
};